package com.wechatnotice.wechatnotice.notifiter;


import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.wechatnotice.wechatnotice.service.NoticeService;
import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent;
import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.Date;
import java.util.Map;
/**
 * <p>
 *  使用Admin监控 自定义监控通知到企业微信
 * </p>
 *
 * @program: WechatNotice
 * @author: daPangDong
 * @create: 2022-10-28 09:17
 */
@Slf4j
@Component
public class CustomNotifier extends AbstractStatusChangeNotifier {

    @Autowired
    private NoticeService noticeService;
    /**
     * 消息模板
     */
    private static final String TEMPLATE = "<<<%s>>> \n 【服务名】: %s(%s) \n 【状态】: %s(%s) \n 【服务ip】: %s \n 【详情】: %s";
    private static final String TEMPLATE_TWO = "%s: <font color=\"warning\">程序正在部署</font>，请相关同事注意\uD83D\uDCA1\n>" +
            "服务名: <font color=\"comment\">%s(%s)</font>\n>" +
            "状态: <font color=\"comment\">%s(%s)</font>\n" +
            "服务ip: <font color=\"comment\">%s</font>\n"+
            "时间: <font color=\"comment\">%s</font>";

    private final String titleAlarm = "系统告警";

    private final String titleNotice = "系统通知";

//    private final String[] ignoreChanges = new String[]{"UNKNOWN:UP","DOWN:UP","OFFLINE:UP"};

    /**
     * 默认情况下监控不到上线的状态
     * 因为父类 AbstractStatusChangeNotifier 的属性 ignoreChanges 忽略了上线状态，不进行通知
     * 故 重写 ignoreChanges 属性 和shouldNotify()方法（其实只修改了ignoreChanges 属性）
     * 将 UNKNOWN:UP 改为 *:* 可以监控所有的状态变化
     */
    private final String[] ignoreChanges = {"*:*"};

    public CustomNotifier(InstanceRepository repository) {
        super(repository);
    }

    @Override
    protected boolean shouldNotify(InstanceEvent event, Instance instance) {
        if (!(event instanceof InstanceStatusChangedEvent)) {
            return false;
        } else {
            InstanceStatusChangedEvent statusChange = (InstanceStatusChangedEvent)event;
            String from = this.getLastStatus(event.getInstance());
            String to = statusChange.getStatusInfo().getStatus();
            return Arrays.binarySearch(this.ignoreChanges, from + ":" + to) < 0 && Arrays.binarySearch(this.ignoreChanges, "*:" + to) < 0 && Arrays.binarySearch(this.ignoreChanges, from + ":*") < 0;
        }
    }

    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
        return Mono.fromRunnable(() -> {
            if (event instanceof InstanceStatusChangedEvent) {
                log.info("Instance {} ({}) is {}", instance.getRegistration().getName(),
                        event.getInstance(),
                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus());
                //服务状态
                String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus();
                //服务详情
                Map<String, Object> details = instance.getStatusInfo().getDetails();
                String messageText;
                String messageType = "";
                switch (status) {
                    // 健康检查没通过
                    case "DOWN":
                        log.info("发送 健康检查没通过 的通知！");
                        //参数
                        // templateTwo 模板
                        // titleNotice,
                        // instance.getRegistration().getName(),
                        // event.getInstance(),
                        // ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(),
                        // "服务上线通知",
                        // instance.getRegistration().getServiceUrl(),
                        // JSONUtil.toJsonStr(details)
//                        messageText = String
//                                .format(template,titleAlarm, instance.getRegistration().getName(), event.getInstance(),
//                                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(), "服务离线通知",
//                                        instance.getRegistration().getServiceUrl(), JSONUtil.toJsonStr(details));
                        messageType = "健康检查没通过通知⛔";
                        break;
                    // 服务离线
                    case "OFFLINE":
                        log.info("发送 服务离线 的通知！");
                        messageType = "服务离线通知❌";
                        break;
                    //服务上线
                    case "UP":
                        log.info("发送 服务上线 的通知！");
                        messageType = "服务上线通知✅";
                        break;
                    // 服务未知异常
                    case "UNKNOWN":
                        log.info("发送 服务未知异常 的通知！");
                        messageType = "服务未知异常通知❗";
                        break;
                    default:
                        break;
                }
                Date date = Date.from(instance.getStatusTimestamp());
                String dateFormat = DateUtil.format(date, DatePattern.CHINESE_DATE_TIME_PATTERN);

                messageText = String.format(TEMPLATE_TWO,
                        titleNotice, instance.getRegistration().getName(), event.getInstance(),
                        status, messageType,
                        instance.getRegistration().getServiceUrl(),dateFormat);
                //先输出信息在控制台
                System.out.println(messageText);
                noticeService.sendByText(messageText,true);
            } else {
                log.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(),
                        event.getType());
            }
        });
    }



}
